package com.jt.service;

import com.jt.vo.ImageVO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;

@Service
@PropertySource("classpath:/image.properties") //动态导入pro配置文件
public class FileServiceImpl implements FileService{
    ////最优做法:应该使用配置文件动态的属性赋值
    @Value("${file.localDirPath}")
    private String localDirPath;     // = "E:/vueDemo/images";
    @Value("${file.preURLPath}")
    private String preURLPath;       // = "http://image.jt.com";
    /**
     * 1. 验证上传的文件是图片 jpg|png|gif等   采用正则表达式校验
     * 2. 防止恶意程序攻击,验证图片是否有宽度和高度
     * 3. 文件分目录存储   例如: /2021/11/11 例如2: hash码 8位hash xx/xx/xx/xx
     *                  数据hahs时 特征:因为是算法 可能造成数据分配不均!!!
     * 4. 防止文件重名,修改文件名称 UUID
     * @param file
     * @return
     */
    @Override
    public ImageVO upload(MultipartFile file) {
        //1. 校验图片类型是否正确
        //1.1 获取文件名称
        String fileName = file.getOriginalFilename();
        //1.3 将名称全部小写
        fileName = fileName.toLowerCase(Locale.ROOT);
        //1.2 正则校验
        if(!fileName.matches("^.+\\.(jpg|png|gif)$")){
            return null;
        }
        //2. 校验文件是否为恶意程序
        //2.1 将文件转化为图片对象
        try {
            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
            int height = bufferedImage.getHeight();
            int width = bufferedImage.getWidth();
            if(height == 0 || width == 0){
                return null;
            }

            //3 实现分目录存储
            //3.1 按照时间分配目录 /yyyy/MM/dd/
            String dateDirPath = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
            //3.2 路径拼接 "E:/vueDemo/images/yyyy/MM/dd/"
            String localDir = localDirPath + dateDirPath;
            File dirFile = new File(localDir);
            if(!dirFile.exists()){ //如果目录不存在,则创建目录
                dirFile.mkdirs();
            }
            //4. 防止文件重名 生成UUID
            String uuid = UUID.randomUUID().toString().replace("-", "");
            int index = fileName.lastIndexOf(".");  //获取文件"."的下标位
            String fileType = fileName.substring(index);//截取文件类型
            String realFileName = uuid + fileType;
            //5. 实现文件上传
            //5.1 拼接文件全路径
            String localFilePath = localDir + realFileName;
            //5.2 完成文件上传
            file.transferTo(new File(localFilePath));

            /**封装返回值
             * virtualPath: 不带磁盘路径 虚拟动态目录
             * E:\vueDemo\images\2021\07\16\662b56c20c4d4176a6eb022ee5248862.png
             */
            String virtualPath = dateDirPath + realFileName;
            String urlPath = preURLPath + virtualPath;
            return new ImageVO(virtualPath, urlPath, realFileName);

        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 1. 拼接文件全路径
     * 2. 执行删除操作
     * @param virtualPath
     */
    @Override
    public void deleteFile(String virtualPath) {
        String path = localDirPath + virtualPath;
        File file = new File(path);
        file.delete();
    }
    /**
     * 步骤:
     *     1.准备文件上传的目录
     *     2.获取文件上传名称
     *     3.拼接文件路径
     *     4.实现文件上传
     *  关于业务层异常处理原则: 将检查异常转化为运行时异常
     * @param file
     */
   /* @Override
    public void upload(MultipartFile file){
        String filePath = "D:/images/";
        File fileDir = new File(filePath);
        //判断目录是否存在
        if(!fileDir.exists()){
            //fileDir.mkdir();  //创建一级目录
            fileDir.mkdirs(); //创建多级目录
        }
        //获取文件名称
        String fileName = file.getOriginalFilename();
        //文件上传目录路径
        String path = filePath + fileName;
        //实现文件上传
        try {
            file.transferTo(new File(path));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }*/
}
